import GameManager from "../GameManager";
import { V2Util } from "../../common/game/util/V2Util";
import App from "../App";
import SnakeMod, { ISnakeNode, ISnake } from "../model/SnakeMod";
import { ClientEvent } from "../event/ClinetEvent";
import BaseView from "../core/mvc/BaseView";

const v2 = V2Util
const et = ClientEvent.Type
const { ccclass, property } = cc._decorator;

@ccclass
export default class SnakeView extends BaseView {

    @property(cc.Prefab)
    snakeNamePre: cc.Node = null
    @property(cc.Prefab)
    snakeNodePre: cc.Node = null
    @property(cc.Prefab)
    snakeHeadPre: cc.Node = null

    nodeMap: Map<number, { node: cc.Node, snakeNode: ISnakeNode, nameNode?: cc.Node }> = new Map()

    namePool: cc.NodePool = null
    nodePool: cc.NodePool = null
    headPool: cc.NodePool = null

    _mod: SnakeMod

    onLoad() {
        this.namePool = new cc.NodePool()
        this.nodePool = new cc.NodePool()
        this.headPool = new cc.NodePool()

        this._mod = SnakeMod.ins

        this.ed.on(et.NODE_LOAD, this, e => {
            e.loadNodes.forEach(snakeNode => {
                let ins = this.nodeMap.get(snakeNode.id)
                let node: cc.Node
                if (!ins) {
                    //没有的先生成
                    let nameNode: cc.Node
                    if (snakeNode.idx == 0) {
                        node = this.headPool.get() || cc.instantiate(this.snakeHeadPre)
                        nameNode = this.namePool.get() || cc.instantiate(this.snakeNamePre)
                        nameNode.getComponent(cc.Label).string = this._mod.getSnake(snakeNode.sid).name
                        nameNode.x = snakeNode.x
                        nameNode.y = snakeNode.y + snakeNode.w
                        nameNode.scale = snakeNode.w / 64
                        nameNode.zIndex = cc.macro.MAX_ZINDEX
                        nameNode.parent = this.node
                    } else {
                        node = this.nodePool.get() || cc.instantiate(this.snakeNodePre)
                    }
                    node.scale = snakeNode.w
                    node.x = snakeNode.x
                    node.y = snakeNode.y
                    node.angle = snakeNode.ang
                    node.name = snakeNode.id.toString()
                    node.color = cc.color(snakeNode.color)
                    node.zIndex = cc.macro.MAX_ZINDEX - snakeNode.idx - 1
                    this.node.addChild(node)
                    this.nodeMap.set(snakeNode.id, { node, snakeNode: snakeNode, nameNode })
                } else {
                    this.nodeMap.get(snakeNode.id).snakeNode = snakeNode
                }
            })
        })

        this.ed.on(et.NODE_UNLOAD, this, e => {
            e.unloadNodeIds.forEach(id => {
                let ins = this.nodeMap.get(id)
                if (ins) {
                    let { node, snakeNode: data, nameNode } = ins
                    if (node) {
                        if (data.idx == 0) {
                            this.headPool.put(node)
                            this.namePool.put(nameNode)
                        } else {
                            this.nodePool.put(node)
                        }
                    }
                    this.nodeMap.delete(id)
                }
            })
        })

    }

    update(dt) {

        this.nodeMap.forEach(_node => {
            let { node, snakeNode, nameNode } = _node

            let smoothing = dt * 8
            node.scale = cc.misc.lerp(node.scale, snakeNode.w, smoothing)
            node.x = cc.misc.lerp(node.x, snakeNode.x, smoothing)
            node.y = cc.misc.lerp(node.y, snakeNode.y, smoothing)
            let diff = v2.angDiff(node.angle, snakeNode.ang)
            node.angle = cc.misc.lerp(node.angle, snakeNode.ang + diff, smoothing)

            if (snakeNode.idx == 0) {
                nameNode.x = cc.misc.lerp(nameNode.x, snakeNode.x, smoothing)
                nameNode.y = cc.misc.lerp(nameNode.y, snakeNode.y + snakeNode.w, smoothing)
                nameNode.scale = cc.misc.lerp(nameNode.scale, snakeNode.w / 64, smoothing)
            }
        })

        if (App.playerId) {
            let snake = this._mod.getSnake(App.playerId)
            if (snake) {
                let head = this.nodeMap.get(snake.hid)
                if (head) {
                    GameManager.focus = head.node
                } else {
                    GameManager.focus = null
                }
            }
        }
    }

}